package com.demo.springmvc底层演示.tomcat;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.apache.catalina.Context;

public class Test {
	
	public static void main(String[] args) throws Exception {
		// 1. 创建tomcat对象
		Tomcat tomcat = new Tomcat();
		tomcat.setBaseDir("tomcat");
		// 2. 创建项目文件夹，即docBase文件夹
		File docBase = com.google.common.io.Files.createTempDir();
		docBase.deleteOnExit();
		// 3. 创建tomcat项目，在tomcat中称为Context
		Context context = tomcat.addContext("", docBase.getAbsolutePath());
		// 4. 编程添加Servlet
		WebApplicationContext springContext = getApplicationContext();
		context.addServletContainerInitializer(new ServletContainerInitializer() {
			
			@Override
			public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
				ctx.addServlet("aaa", HelloServlet.class).addMapping("/hello");
				for(ServletRegistrationBean registrationBean : springContext.getBeansOfType(ServletRegistrationBean.class).values()) {
					registrationBean.onStartup(ctx);
				}
			}
		}, Collections.emptySet());
		// 6. 创建连接器，设置监听端口
		Connector connector = new Connector("HTTP/1.1");
		connector.setPort(8080);
		tomcat.setConnector(connector);
		// 5. 启动tomcat
		tomcat.start();
		System.in.read();
	}
	
	public static WebApplicationContext getApplicationContext() {
		// 使用了非内嵌tomcat的容器，因为上面已经手动创建tomcat了
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(Config.class);
		context.refresh();
		return context;
	}
	
	@Configuration
	static class Config {
		@Bean
		public ServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet) {
			ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet, "/");
			registration.setLoadOnStartup(1);
			return registration;
		}
		@Bean
		public DispatcherServlet dispatcherServlet(AnnotationConfigWebApplicationContext context) {
			return new DispatcherServlet(context);
		}
		@Bean
		public RequestMappingHandlerMapping requestMappingHandlerMapping() {
			return new RequestMappingHandlerMapping();
		}
		@Bean
		public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
			RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
			List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>() {{
				add(new MappingJackson2HttpMessageConverter());
			}};
			handlerAdapter.setMessageConverters(messageConverters);
			return handlerAdapter;
		}
		
		@RestController
		static class MyController {
			public MyController() {
				System.out.println();
			}
			@GetMapping("/hello2")
			public Map<String, Object> hello() {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("hello2", "hello2, spring");
				return map;
			}
		}
		
	}

}
